<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <link type="text/css" rel="stylesheet" href="css/active4d.css">
        <link type="text/css" rel="stylesheet" href="css/main.css">
        <title>In-depth introduction for E4X</title>
    </head>
    <body>
        <h1>E4X <a class='hh' name='E4X'>⁋</a></h1><p>E4X, short for "ECMAScript for XML", is an extension to <a href="EcmaScript.html">EcmaScript</a> (i.e. JavaScript, JScript, ActionScript) with new syntax and built-in objects for more convenient handling of XML fragments. It seems to be used most frequently with <a href="ActionScript.html">ActionScript</a> 3 (Flash), but is also available in recent Mozilla/Firefox releases.</p><p>I whipped up this guide after a quick read-through of the <a href="http://www.ecma-international.org/publications/standards/Ecma-357.htm">specification</a> and a bit of playing around. </p><p>In order, it briefly outlines:</p><ul><li>The syntax for declaring literal XML values</li><li><code>XML</code> and <code>XMLList</code> objects</li><li>Variable interpolation in XML literals</li><li>The new syntax for traversal of <code>XML</code> objects</li><li>Namespace considerations</li><li>The methods of <code>XML</code> objects</li></ul>
<h2>First-class XML <a class='hh' name='First-class_XML'>⁋</a></h2><p>E4X <code>XML</code> objects can be created by passing a string to the <code>XML</code> constructor function, but that’s hardly exciting. Much more interesting is the new syntax for <code>XML</code> literals, similar to that in Scala. It’s exactly what you’d expect:</p><pre class="active4d code-block">
  let x <span class="Operator">=</span> <span class="Operator">&lt;</span>elm id<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>1<span class="String">&quot;</span></span><span class="Operator">&gt;</span>
    <span class="Operator">&lt;</span>a<span class="Operator">&gt;</span>content<span class="Operator">&lt;</span>/a<span class="Operator">&gt;</span>
  <span class="Operator">&lt;</span>/elm<span class="Operator">&gt;</span>;
</pre><p>There’s no more need to bother with painful string concatenation or backslashed line continuations.</p><p>Even better, <code>XML</code> objects are first-class citizens. They have properties and methods; they can be deleted, concatenated and iterated over.</p><pre class="active4d code-block">
  let y <span class="Operator">=</span> x <span class="Operator">+</span> <span class="Operator">&lt;</span>elm id<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>2<span class="String">&quot;</span></span> /<span class="Operator">&gt;</span>;
  let name <span class="Operator">=</span> <span class="Operator">&lt;</span>xml /<span class="Operator">&gt;</span>.<span class="NamedConstant">name</span>();
</pre>
<h2><code>XML</code> and <code>XMLList</code> <a class='hh' name='<code>XML</code>_and_<code>XMLList</code>'>⁋</a></h2><p>As well as <code>XML</code>, E4X defines the <code>XMLList</code>, an ordered collection of <code>XML</code> objects similar to the W3C DOM NodeList.</p><p>The literal syntax is rather less intuitive:</p><pre class="active4d code-block">
  let xl <span class="Operator">=</span> <span class="Operator">&lt;&gt;</span>
    <span class="Operator">&lt;</span>a /<span class="Operator">&gt;</span>
    <span class="Operator">&lt;</span>b /<span class="Operator">&gt;</span>
    <span class="Operator">&lt;</span>c /<span class="Operator">&gt;</span>
  <span class="Operator">&lt;</span>/<span class="Operator">&gt;</span>;
</pre><p>Much of E4X’s expressive power comes from the blurring of the line between <code>XMLList</code> and <code>XML</code> objects. Both have a type of "xml"; <code>instanceof xml</code> returns <code>true</code> for both.</p><p>The advantage is that you rarely need to worry about which you have. A single-item <code>XMLList</code> is treated identically to an <code>XML</code> object, and even longer lists share many of the same methods. The <code>text()</code> method of an <code>XML</code> object returns its text content. On an <code>XMLList</code> it returns the concatenated text content of all list members.</p><p>If you do need to tell the difference, just check the <code>.length()</code>: an <code>XML</code> object’s length is always 1. <h2>Literal Interpolation <a class='hh' name='Literal_Interpolation'>⁋</a></h2></p><p>When declaring a literal, expressions inside braces (curly brackets) are automatically evaluated.</p><pre class="active4d code-block">
  let name <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span>bob^%*<span class="String">&quot;</span></span>;
  let tag <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span>person<span class="String">&quot;</span></span>;
  let p <span class="Operator">=</span> <span class="Operator">&lt;</span>{tag} id<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>3<span class="String">&quot;</span></span><span class="Operator">&gt;</span>
      {name.<span class="CommandMethod">replace</span>(<span class="String"><span class="String">/</span>[^a-z]<span class="String">/</span>ig</span>, <span class="String"><span class="String">&quot;</span><span class="String">&quot;</span></span>)}
    <span class="Operator">&lt;</span>/{tag}<span class="Operator">&gt;</span>; <span class="LineComment"><span class="LineComment">//</span></span>
  <span class="CommandMethod">print</span>( p.<span class="CommandMethod">toString</span>(); ) <span class="LineComment"><span class="LineComment">//</span> =&gt; &lt;person id=&quot;3&quot;&gt;bob&lt;/person&gt;</span>
</pre><p>Braced values are not, however, evaluated in CDATA sections, such as the contents of attribute values:</p><pre class="active4d code-block">
  let att <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span>id<span class="String">&quot;</span></span>;
  let val  <span class="Operator">=</span> <span class="Number">3</span>;
  let a <span class="Operator">=</span> <span class="Operator">&lt;</span>person {att}<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>{val}<span class="String">&quot;</span></span><span class="Operator">&gt;</span>bob<span class="Operator">&lt;</span>/person<span class="Operator">&gt;</span>; <span class="LineComment"><span class="LineComment">//</span></span>
  <span class="CommandMethod">print</span>( a.<span class="CommandMethod">toString</span>() ) <span class="LineComment"><span class="LineComment">//</span> =&gt; &lt;person id=&quot;{val}&quot;&gt;bob&lt;/person&gt;</span>
  
  let b <span class="Operator">=</span> <span class="Operator">&lt;</span>person {att}<span class="Operator">=</span>{val}<span class="Operator">&gt;</span>bob<span class="Operator">&lt;</span>/person<span class="Operator">&gt;</span>; <span class="LineComment"><span class="LineComment">//</span></span>
  <span class="CommandMethod">print</span>( p.<span class="CommandMethod">toString</span>() ) <span class="LineComment"><span class="LineComment">//</span> =&gt; // &lt;person id=&quot;3&quot;&gt;bob&lt;/person&gt;</span>
</pre><p>Interpolated attribute values are automatically quoted; any <code>XML</code> entities are automatically escaped.</p><pre class="active4d code-block">
  val <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">%content%quot;</span>&lt;&gt;<span class="String">&quot;</span></span>;
  b <span class="Operator">=</span> <span class="Operator">&lt;</span>person {att}<span class="Operator">=</span>{val}<span class="Operator">&gt;</span>bob<span class="Operator">&lt;</span>/person<span class="Operator">&gt;</span> <span class="LineComment"><span class="LineComment">//</span></span>
  <span class="CommandMethod">print</span>( p.<span class="CommandMethod">toString</span>() ) <span class="LineComment"><span class="LineComment">//</span> =&gt; &lt;person id=&quot;&amp;quot;&amp;lt;&gt;&quot;&gt;bob&lt;/person&gt;</span>
</pre><p>Literal braces should be escaped as <code>&#x7B;</code> and <code>&x#7D;</code> for <code>{</code> and <code>}</code> respectively. Accessing XML Properties</p><p><code>XML</code> objects can be filtered and traversed using an object syntax similar to <code>ElementTree</code> and <code>BeautifulSoup</code>, with a bit of <code>XPath</code> thrown in.</p><p>A node’s child elements can be accessed as properties:</p><pre class="active4d code-block">
  let x <span class="Operator">=</span> <span class="Operator">&lt;</span>people <span class="Storage">class</span><span class="Operator">=</span><span class="String"><span class="String">&quot;</span>example<span class="String">&quot;</span></span><span class="Operator">&gt;</span>
      <span class="Operator">&lt;</span>person id<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>1<span class="String">&quot;</span></span><span class="Operator">&gt;</span><span class="Operator">&lt;</span>name<span class="Operator">&gt;</span>sam<span class="Operator">&lt;</span>/name<span class="Operator">&gt;</span><span class="Operator">&lt;</span>/person<span class="Operator">&gt;</span>
      <span class="Operator">&lt;</span>person id<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>2<span class="String">&quot;</span></span><span class="Operator">&gt;</span><span class="Operator">&lt;</span>name<span class="Operator">&gt;</span>elizabeth<span class="Operator">&lt;</span>/name<span class="Operator">&gt;</span><span class="Operator">&lt;</span>/person<span class="Operator">&gt;</span>
    <span class="Operator">&lt;</span>/people<span class="Operator">&gt;</span>; <span class="LineComment"><span class="LineComment">//</span></span>
 
  let names <span class="Operator">=</span> x.person.<span class="NamedConstant">name</span>;
  let name  <span class="Operator">=</span> x.person[<span class="Number">0</span>].<span class="NamedConstant">name</span>;
 
  <span class="CommandMethod">print</span>( names.toXMLString() ) <span class="LineComment"><span class="LineComment">//</span> =&gt; &lt;name&gt;sam&lt;/name&gt; &lt;name&gt;elizabeth&lt;/name&gt;</span>
  
  <span class="CommandMethod">print</span>( name.toXMLString() ) <span class="LineComment"><span class="LineComment">//</span> =&gt; &lt;name&gt;sam&lt;/name&gt;</span>
</pre><p><code>x.[name]</code> is the same as <code>x.child([name])</code>. <h2>Attributes <a class='hh' name='Attributes'>⁋</a></h2></p><p>As with XPath, <code>@</code> is used to access attributes.</p><pre class="active4d code-block">
  let id <span class="Operator">=</span> x.person[<span class="Number">0</span>].@id;
  
  <span class="LineComment"><span class="LineComment">//</span> x.@[name] is identical to x.attribute([name]).</span>
</pre>
<h2>Descendants <a class='hh' name='Descendants'>⁋</a></h2><p>The <code>..</code> operator accesses all descendants, not just the immediate children.</p><pre class="active4d code-block">
  let names <span class="Operator">=</span> x..<span class="NamedConstant">name</span>;
  let ids <span class="Operator">=</span> x..@id;
  
  <span class="LineComment"><span class="LineComment">//</span> x..[name] is equivalent to x.descendants([name]).</span>
</pre> 
<h2>The Wildcard <a class='hh' name='The_Wildcard'>⁋</a></h2><p>The <code>*</code> wildcard matches all names.</p><pre class="active4d code-block">
  let persons  <span class="Operator">=</span> x.<span class="Operator">*</span>;
  let all      <span class="Operator">=</span> x..<span class="Operator">*</span>;
  let attrs    <span class="Operator">=</span> x..@<span class="Operator">*</span>;
</pre><p>The wildcard is magic in more than one context, but in this one it’s equivalent to <code>QName(null, "*")</code>.</p><pre class="active4d code-block">
  let all <span class="Operator">=</span> x.descendants(QName(<span class="BuiltInConstant">null</span>, <span class="String"><span class="String">&quot;</span>*<span class="String">&quot;</span></span>));
</pre>
<h2>Filtering Predicates <a class='hh' name='Filtering_Predicates'>⁋</a></h2><pre class="active4d code-block">
  let me     <span class="Operator">=</span> x.person.(name <span class="Operator">==</span> <span class="String"><span class="String">&quot;</span>sam<span class="String">&quot;</span></span>);
  let either <span class="Operator">=</span> x.person.(@id <span class="Operator">==</span> <span class="Number">1</span> <span class="Operator">||</span> @id <span class="Operator">==</span> <span class="Number">2</span>);
</pre><p>Predicates can be nested and quite complex:</p><pre class="active4d code-block">
  let me <span class="Operator">=</span> x..<span class="Operator">*</span>.(name <span class="Operator">==</span> <span class="String"><span class="String">&quot;</span>sam<span class="String">&quot;</span></span> <span class="Operator">&amp;</span><span class="Operator">&amp;</span> 
        name.<span class="NamedConstant">parent</span>().(@id <span class="Operator">==</span> <span class="Number">1</span>).<span class="NamedConstant">name</span>() <span class="Operator">==</span> <span class="String"><span class="String">&quot;</span>person<span class="String">&quot;</span></span>);
</pre><p>They’re not quite as useful as they could be, however. Unlike XPath, E4X expressions cannot easily be used to search ancestor axes.</p><p>The previous example illustrates a potential problem. It only works because the list of matches is reduced to one by <code>(name == "sam")</code> before the <code>parent()</code> method is invoked.</p><p>This expression, on the other hand, will raise an exception:</p><pre class="active4d code-block">
  x..<span class="Operator">*</span>.(name.<span class="NamedConstant">parent</span>().@id <span class="Operator">==</span> <span class="Number">1</span>);
</pre><p>The filter does not examine the parent of every name in turn; it looks for the single parent of the entire list of names together. It returns <code>undefined</code> unless every member shares the same parent. Deletion</p><p>The delete keyword works on arbitrary E4X expressions:</p><pre class="active4d code-block">
  <span class="Operator">delete</span> x.person.(@id <span class="Operator">==</span> <span class="Number">1</span>); <span class="LineComment"><span class="LineComment">//</span> that's me gone </span>
  <span class="Operator">delete</span> x..person            <span class="LineComment"><span class="LineComment">//</span> ... and everyone else</span>
</pre>
<h2>Assignment <a class='hh' name='Assignment'>⁋</a></h2><p>You can also use the normal assignment operator:</p><pre class="active4d code-block">
  x..<span class="NamedConstant">name</span>[<span class="Number">0</span>] <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span>batman<span class="String">&quot;</span></span>;
  x.@pointless <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span>new attribute!<span class="String">&quot;</span></span>;
  x.person <span class="Operator">+</span><span class="Operator">=</span> <span class="Operator">&lt;</span>person id<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>3<span class="String">&quot;</span></span><span class="Operator">&gt;</span><span class="Operator">&lt;</span>name<span class="Operator">&gt;</span>alfred<span class="Operator">&lt;</span>/name<span class="Operator">&gt;</span><span class="Operator">&lt;</span>/person<span class="Operator">&gt;</span>; 
</pre><p>In some circumstances you can also assign to an expression that would return a list:</p><pre class="active4d code-block">
  x.<span class="Operator">*</span> <span class="Operator">=</span> <span class="Operator">&lt;</span>goodbye_previous_content /<span class="Operator">&gt;</span>;
</pre><p>But those nodes were all together, so replacing them at once is a natural operation. This, on the other hand, is illegal:</p><pre class="active4d code-block">
  x.person.@newattributes <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span>for all<span class="String">&quot;</span></span>;
</pre>
<h2>Iteration <a class='hh' name='Iteration'>⁋</a></h2><p>There are several ways to iterate over <code>XMLList</code> and <code>XML</code> objects, though for XML the exercise is meaningless:</p><pre class="active4d code-block">
  x[<span class="Number">0</span>] <span class="Operator">==</span> x; <span class="LineComment"><span class="LineComment">//</span> =&gt; true</span>
</pre>
  
Nevertheless. First, iteration over list indices:<pre class="active4d code-block">
  <span class="Keyword">for</span> (let i <span class="Operator">in</span> x..<span class="Operator">*</span>) {
      elm <span class="Operator">=</span> x..<span class="Operator">*</span>[i];
  }
</pre><p>The same can be accomplished with a <code>for;;</code> loop and the <code>length()</code> method.</p><pre class="active4d code-block">
  <span class="Keyword">for</span> (let i<span class="Operator">=</span><span class="Number">0</span>; i<span class="Operator">&lt;</span>x.<span class="NamedConstant">length</span>(); <span class="Operator">++</span>i) {
      elm <span class="Operator">=</span> x[i];
  }
</pre><p>Most useful of all, though, is the new <code>for each ..</code> in syntax, allowing direct manipulation of matching nodes:</p><pre class="active4d code-block">
  <span class="Keyword">for</span> each (let elm <span class="Operator">in</span> x.person) {
      elm.@id <span class="Operator">+</span><span class="Operator">=</span> <span class="Number">1</span>;
  }
</pre>
<h2>Namespaces <a class='hh' name='Namespaces'>⁋</a></h2><p>E4X has robust namespace support, but (as anyone with XML experience must expect) they complicate an otherwise simple model.</p><pre class="active4d code-block">
  let x <span class="Operator">=</span> <span class="Operator">&lt;</span>xml<span class="Operator">&gt;</span>
          <span class="Operator">&lt;</span>v1<span class="Operator">&gt;</span>value one<span class="Operator">&lt;</span>/v1<span class="Operator">&gt;</span>
          <span class="Operator">&lt;</span>v2<span class="Operator">&gt;</span>value two<span class="Operator">&lt;</span>/v2<span class="Operator">&gt;</span>
      <span class="Operator">&lt;</span>/xml<span class="Operator">&gt;</span>; <span class="LineComment"><span class="LineComment">//</span></span>
 
  x.v1 <span class="Operator">==</span> <span class="String"><span class="String">&quot;</span>value one<span class="String">&quot;</span></span>; <span class="LineComment"><span class="LineComment">//</span> =&gt; true</span>
</pre>
  <p>With namespaces, you have to use a qualified name.</p><pre class="active4d code-block">
  let x <span class="Operator">=</span> <span class="Operator">&lt;</span>xml xmlns<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>http://example.com/<span class="String">&quot;</span></span><span class="Operator">&gt;</span>
          <span class="Operator">&lt;</span>v1<span class="Operator">&gt;</span>value one<span class="Operator">&lt;</span>/v1<span class="Operator">&gt;</span>
          <span class="Operator">&lt;</span>v2<span class="Operator">&gt;</span>value two<span class="Operator">&lt;</span>/v2<span class="Operator">&gt;</span>
      <span class="Operator">&lt;</span>/xml<span class="Operator">&gt;</span>; <span class="LineComment"><span class="LineComment">//</span></span>
 
  x.v1 <span class="Operator">==</span> undefined; <span class="LineComment"><span class="LineComment">//</span> =&gt; true</span>
 
  let example <span class="Operator">=</span> Namespace(<span class="String"><span class="String">&quot;</span>http://example.com/<span class="String">&quot;</span></span>);
  x.example::v1 <span class="Operator">==</span> <span class="String"><span class="String">&quot;</span>value one<span class="String">&quot;</span></span>; <span class="LineComment"><span class="LineComment">//</span> =&gt; true</span>
</pre><p>Note the use of the <code>::</code> scoping operator. You can also suggest a namespace prefix and/or or construct the <code>QName()</code> directly:</p><pre class="active4d code-block">
  let example <span class="Operator">=</span> Namespace(<span class="String"><span class="String">&quot;</span>example<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>http://example.com/<span class="String">&quot;</span></span>);
  let name <span class="Operator">=</span> QName(example, <span class="String"><span class="String">&quot;</span>v1<span class="String">&quot;</span></span>);
  let same <span class="Operator">=</span> QName(<span class="String"><span class="String">&quot;</span>http://example.com/<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>v1<span class="String">&quot;</span></span>);
</pre><p>If more liberal matching is required, the <code>*</code> wildcard signifies any namespace.</p><pre class="active4d code-block">
  x.<span class="Operator">*</span>::v1 <span class="Operator">==</span> <span class="String"><span class="String">&quot;</span>value one<span class="String">&quot;</span></span>; <span class="LineComment"><span class="LineComment">//</span> =&gt; true</span>
</pre><p>The wildcard anyname-namespace is different from the unnamed namespace, and can also be created by passing <code>null</code> to the Namespace constructor. The following are equivalent:</p><pre class="active4d code-block">
  x.<span class="Operator">*</span>::v1
  x.child(QName(<span class="BuiltInConstant">null</span>, <span class="String"><span class="String">&quot;</span>v1<span class="String">&quot;</span></span>));
</pre>
<h2>The default namespace <a class='hh' name='The_default_namespace'>⁋</a></h2><p>Using perhaps the most self-explanatory syntax ever devised, you can set the default XML namespace in the current scope.</p><pre class="active4d code-block">
  let example <span class="Operator">=</span> Namespace(<span class="String"><span class="String">&quot;</span>http://example.com/<span class="String">&quot;</span></span>);
  <span class="Keyword">default</span> xml namespace <span class="Operator">=</span> example;
  <span class="LineComment"><span class="LineComment">//</span> or</span>
  <span class="Keyword">default</span> xml namespace <span class="Operator">=</span> <span class="String"><span class="String">&quot;</span>http://example.com/<span class="String">&quot;</span></span>;
  
  let x <span class="Operator">=</span> <span class="Operator">&lt;</span>xml /<span class="Operator">&gt;</span>; <span class="LineComment"><span class="LineComment">//</span></span>
  <span class="CommandMethod">print</span>( x.toXMLString() ) <span class="LineComment"><span class="LineComment">//</span> =&gt; &lt;xml xmlns=&quot;http://example.com/&quot;/&gt;</span>
</pre><p>To reiterate: in the current scope. <h2><code>toString()</code> vs. <code>toXMLString()</code> <a class='hh' name='<code>toString()</code>_vs._<code>toXMLString()</code>'>⁋</a></h2></p><p>There is an important difference between the <code>toString()</code> and <code>toXMLString()</code> methods.</p><pre class="active4d code-block">
  let x <span class="Operator">=</span> <span class="Operator">&lt;</span>people<span class="Operator">&gt;</span>
      <span class="Operator">&lt;</span>person id<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>1<span class="String">&quot;</span></span><span class="Operator">&gt;</span><span class="Operator">&lt;</span>name<span class="Operator">&gt;</span>sam<span class="Operator">&lt;</span>/name<span class="Operator">&gt;</span><span class="Operator">&lt;</span>/person<span class="Operator">&gt;</span>
      <span class="Operator">&lt;</span>person id<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>2<span class="String">&quot;</span></span><span class="Operator">&gt;</span><span class="Operator">&lt;</span>name<span class="Operator">&gt;</span>elizabeth<span class="Operator">&lt;</span>/name<span class="Operator">&gt;</span><span class="Operator">&lt;</span>/person<span class="Operator">&gt;</span>
  <span class="Operator">&lt;</span>/people<span class="Operator">&gt;</span>; <span class="LineComment"><span class="LineComment">//</span></span>
 
  let names <span class="Operator">=</span> x.person.<span class="NamedConstant">name</span>;
  let name <span class="Operator">=</span> x.person[<span class="Number">0</span>].<span class="NamedConstant">name</span>;
  
  <span class="CommandMethod">print</span>( names.toXMLString() ) <span class="LineComment"><span class="LineComment">//</span> =&gt; &lt;name&gt;sam&lt;/name&gt; &lt;name&gt;elizabeth&lt;/name&gt;</span>
  <span class="CommandMethod">print</span>( name.toXMLString() )  <span class="LineComment"><span class="LineComment">//</span> =&gt; &lt;name&gt;sam&lt;/name&gt;</span>
  
  <span class="CommandMethod">print</span>( names.<span class="CommandMethod">toString</span>() )    <span class="LineComment"><span class="LineComment">//</span> =&gt; &lt;name&gt;sam&lt;/name&gt; &lt;name&gt;elizabeth&lt;/name&gt;</span>
  <span class="CommandMethod">print</span>( name.<span class="CommandMethod">toString</span>() )     <span class="LineComment"><span class="LineComment">//</span> =&gt; sam</span>
</pre><p><code>toString()</code> returns different values depending on whether or not an object is considered “complex”. If there are no child elements (other types, such as XML comments, don’t count), it returns the element’s text content only. This is very useful in most cases but a painful gotcha in others. <h2>Extending E4X <a class='hh' name='Extending_E4X'>⁋</a></h2></p><p><a href="EcmaScript.html">EcmaScript</a> lets you do wonderful things by extending <code>Object.prototype</code>, <code>String.prototype</code> etc. with new methods.</p><p><strike>It’s much harder with E4X. The prototypes of <code>XML</code> and <code>XMLList</code> are read-only, so new methods can’t be added directly. Most of their existing methods throw exceptions if they are applied to any other object. Procedural code will have to do.</strike></p><p>In <a href="JooScript.html">JooScript</a> <code>XML</code> and <code>XMLList</code> are internal classes. But they are extensible.</p><p>Future versions will have built-in support for custom types based on XML schemas. <h2>Global function reference <a class='hh' name='Global_function_reference'>⁋</a></h2></p><pre class="active4d code-block">
  isXMLName( value ) : bool
</pre><p>Is the value usable as an XML name? <h2>XML Constructor Reference <a class='hh' name='XML_Constructor_Reference'>⁋</a></h2></p><p>The <code>XML</code> constructor has several properties managing global settings for XML processing and serialization.</p><pre class="active4d code-block">
  XML.ignoreComments <span class="Operator">=</span> <span class="BuiltInConstant">false</span>
</pre><p>Ignore XML comments. (Default: <code>true</code>)</p><pre class="active4d code-block">
  XML.ignoreProcessingInstructions <span class="Operator">=</span> <span class="BuiltInConstant">false</span>
</pre><p>Ignore XML processing instructions. (Default: <code>true</code>)</p><pre class="active4d code-block">
  XML.ignoreWhitespace <span class="Operator">=</span> <span class="BuiltInConstant">false</span>
</pre><p>Ignore whitespace. (Default: <code>true</code>)</p><pre class="active4d code-block">
  XML.prettyPrinting <span class="Operator">=</span> <span class="BuiltInConstant">false</span>
</pre><p>Pretty-print XML output with <code>toXMLString()</code> etc. (Default: <code>true</code>)</p><pre class="active4d code-block">
  XML.prettyIndent <span class="Operator">=</span> <span class="BuiltInConstant">false</span>
</pre><p>Pretty indent level for child nodes. (Default: 2)</p><p>---</p><p>There are also three methods to more easily apply and restore settings for use, say, within a function.</p><pre class="active4d code-block">
  XML.settings()
</pre><p>Get an Object containing the above settings.</p><pre class="active4d code-block">
  XML.defaultSettings()
</pre><p>Get an object containing the default settings.</p><pre class="active4d code-block">
  XML.setSettings([settings])
</pre><p>Set XML settings from, e.g., an object returned by <code>XML.settings()</code>. <h2>XML Object Reference <a class='hh' name='XML_Object_Reference'>⁋</a></h2></p><pre class="active4d code-block">
  xnode.addNamespace([namespace])
</pre><p>Add a namespace declaration to the object.</p><pre class="active4d code-block">
  xnode.<span class="CommandMethod">appendChild</span>(child)
</pre><p>Append a node to the object’s list of children.</p><pre class="active4d code-block">
  xnode.attribute(attributeName)
</pre><p>Returns an <code>XMLList</code> of zero or one matching attributes.  Same as <code>element.@attributeName</code>.</p><pre class="active4d code-block">
  xnode.<span class="NamedConstant">attributes</span>()
</pre><p>Returns an <code>XMLList</code> of attributes.  Same as <code>element.@*</code></p><pre class="active4d code-block">
  xnode.child(propertyName or index)
</pre><p>Same as <code>element.propertyName</code> or <code>element[index]</code>.</p><pre class="active4d code-block">
  xnode.childIndex()
</pre><p>Returns the node’s position in the parent’s list of children, or -1 if there is no parent or its children are unordered.</p><pre class="active4d code-block">
  xnode.children()
</pre><p>Returns an <code>XMLList</code> of children.  Same as <code>element.*</code>.</p><pre class="active4d code-block">
  xnode.comments()
</pre><p>Returns an <code>XMLList</code> of child nodes that are comments.  Same as <code>element.(*.nodeKind() == 'comment')</code>.</p><pre class="active4d code-block">
  xnode.contains(value)
</pre><p>Same as <code>element == value</code>.</p><pre class="active4d code-block">
  xnode.copy()
</pre><p>Return a deep copy of the object, detached from its parent.</p><pre class="active4d code-block">
  descendants(name)
</pre><p>Return all descendants with the given name, or, if name is <code>null</code> or <code>undefined</code>, all descendants.  Same as <code>element..name</code>.</p><pre class="active4d code-block">
  xnode.<span class="NamedConstant">elements</span>([name])
</pre><p>Returns all child elements with the given name, or, if name is <code>null</code> or <code>undefined</code>, all child elements.  Same as <code>element.(*.nodeKind() == 'element')</code>.</p><pre class="active4d code-block">
  xnode.hasOwnProperty(prop)
</pre><p>The same as on any other object.</p><pre class="active4d code-block">
  xnode.hasComplexContent()
</pre><p>Returns true if the node has complex content (in effect, if it has child elements). <pre class="active4d code-block">   xnode.hasSimpleContent() </pre></p><p>The opposite of <code>hasComplexContent()</code>.</p><pre class="active4d code-block">
  xnode.inScopeNamespaces()
</pre><p>Returns an <code>Array</code> of in-scope <code>Namespace</code> objects.</p><pre class="active4d code-block">
  xnode.insertChildAfter(anchor, child)
  xnode.insertChildBefore(anchor, child)
</pre><p>Insert a child node before or after the specified anchor node. If the anchor is <code>null</code>, insert before or after no nodes.</p><p>If the anchor is not in this <code>XML</code> object, do nothing.</p><pre class="active4d code-block">
  xnode.<span class="NamedConstant">length</span>()
</pre><p>Return the length of the object. For <code>XML</code> objects always return 1.</p><pre class="active4d code-block">
  xnode.<span class="NamedConstant">localName</span>()
</pre><p>Return the local part of the qualified name. (A node’s name not including its namespace.)</p><pre class="active4d code-block">
  xnode.<span class="NamedConstant">name</span>()
</pre><p>Return the qualified name. (Including namespace.)</p><pre class="active4d code-block">
  let x <span class="Operator">=</span> <span class="Operator">&lt;</span>xml xmlns<span class="Operator">=</span><span class="String"><span class="String">&quot;</span>http://example.com/<span class="String">&quot;</span></span><span class="Operator">&gt;</span>abc<span class="Operator">&lt;</span>/xml<span class="Operator">&gt;</span>; <span class="LineComment"><span class="LineComment">//</span></span>
  x.<span class="NamedConstant">name</span>() <span class="Operator">==</span> <span class="String"><span class="String">&quot;</span>http://example.com/::xml<span class="String">&quot;</span></span>;
  x.<span class="NamedConstant">localName</span>() <span class="Operator">==</span> <span class="String"><span class="String">&quot;</span>xml<span class="String">&quot;</span></span>;
  x.namespace() <span class="Operator">==</span> <span class="String"><span class="String">&quot;</span>http://example.com/<span class="String">&quot;</span></span>;
</pre><pre class="active4d code-block">
  xnode.namespace([prefix])
</pre><p>Return the in-scope namespace specified by prefix, or:</p><ul><li>If no namespace matches, return <code>undefined</code>.</li><li>If prefix is not provided, return the default namespace.</li></ul><pre class="active4d code-block">
  xnode.namespaceDeclarations()
</pre><p>Return an Array of Namespace objects representing namespaces declared (as in assigned a prefix) on this <code>XML</code> object.</p><pre class="active4d code-block">
  xnode.nodeKind()
</pre><p>Returns the type of <code>XML</code> node, one of attribute, element, comment, processing-instruction, text.</p><pre class="active4d code-block">
  xnode.normalize()
</pre><p>Merge adjacent text nodes and remove empty text nodes on this all descendants.</p><pre class="active4d code-block">
  xnode.<span class="NamedConstant">parent</span>()
</pre><p>Return the parent node. On an <code>XMLList</code>, this method returns <code>undefined</code> unless all members share the same parent.</p><pre class="active4d code-block">
  xnode.processingInstructions([ name ])
</pre><p>Returns all child processing instructions with the given name, or, if name is <code>null</code> or <code>undefined</code>, all child processing instructions.  Same as <code>element.(*.nodeKind() == 'processing-instruction')</code>.</p><pre class="active4d code-block">
  xnode.prependChild(value)
</pre><p>Insert value at the beginning of the object’s child nodes.</p><pre class="active4d code-block">
  xnode.propertyIsEnumerable(prop)
</pre><p>Will the specified property be enumerated in a for .. in loop? Same as for other objects.</p><pre class="active4d code-block">
  xnode.removeNamespace(namespace)
</pre><p>If possible, remove the given namespace from the object and all descendants. removeNamespace will not remove a namespace if it is referenced in that object or any of its children.</p><pre class="active4d code-block">
  xnode.<span class="CommandMethod">replace</span>(propertyName, value)
</pre><p>Replace value specified by propertyName, where <code>propertyName</code> is a name, numeric index or <code>*</code> wildcard, with value.</p><pre class="active4d code-block">
  xnode.setChildren(value)
</pre><p>Replace the object’s children with value.</p><pre class="active4d code-block">
  xnode.setLocalName(name)
</pre><p>Change the object’s local name using a string or the localName property of a <code>QName</code> object.</p><pre class="active4d code-block">
  xnode.setName(name)
</pre><p>Set the object’s name and alter the in-scope namespaces to fit.</p><pre class="active4d code-block">
  xnode.setNamespace(ns)
</pre><p>Replace the object’s default namespace with ns.</p><pre class="active4d code-block">
  xnode.<span class="NamedConstant">text</span>()
</pre><p>Returns all child text nodes with the given name, or, if name is <code>null</code> or <code>undefined</code>, all child text nodes.  Same as <code>element.(*.nodeKind() == 'text')</code>.</p><pre class="active4d code-block">
  xnode.<span class="CommandMethod">toString</span>()
</pre><p>Returns a string representation. Elements with simple content (i.e., no child elements) are returned as text; complex elements are returned as XML.</p><pre class="active4d code-block">
  xnode.toXMLString()
</pre><p>An XML serialization of the object.</p><pre class="active4d code-block">
  xnode.<span class="CommandMethod">valueOf</span>()
</pre><p>Return this object. <h2>XMLList Reference <a class='hh' name='XMLList_Reference'>⁋</a></h2></p><p>Most methods are the same. Descendant methods such as <code>children()</code> and <code>text()</code> are simply applied to all members of the list and the results combined. Others, like <code>parent()</code>, don’t work when it isn’t logical that they do so — consult your common sense. <h2>Optional Features <a class='hh' name='Optional_Features'>⁋</a></h2></p><p>Implementations are allowed to include these optional features, or not. Currently Mozilla seems to be on the “or not” side of the fence, but they’re easy enough to implement in userspace if you need them. <h3><code>domNode()</code> <a class='hh' name='<code>domNode()</code>'>⁋</a></h3></p><p>Return a W3C DOM node representation of the object.</p><pre class="active4d code-block">
  xnode.domNodeList()
</pre><p>Return a W3C DOM <code>NodeList</code> representation.</p><pre class="active4d code-block">
  xnode.xpath(exp)
</pre><p>Apply the <code>XPath</code> expression <code>exp</code> and either return an <code>XMLList</code> of results or throw a <code>TypeError</code>.  <i>Source: <a href="http://rephrase.net/days/07/06/e4x.html">http://rephrase.net/days/07/06/e4x</a></i></p>
        <hr/>
        Updated: Tue Nov 23 21:42:10 +0300 2010
    </body>
</html>
